package org.dromara.iot.handler;

import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.domain.R;
import org.dromara.iot.domain.DeviceReport;
import org.dromara.iot.domain.IotCarPersonEvent;
import org.dromara.iot.domain.RfidTag;
import org.dromara.iot.domain.vo.IotXfclDeviceBindVo;
import org.dromara.iot.domain.vo.IotXfjyryRfidBindVo;
import org.dromara.iot.mapper.IotXfclDeviceBindMapper;
import org.dromara.iot.mapper.IotXfjyryRfidBindMapper;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageHandler;
import org.springframework.messaging.MessagingException;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;

import java.io.IOException;
import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.stream.Collectors;

@Slf4j
@Component
public class ReceiverMessageHandler implements MessageHandler {
    private final List<SseEmitter> emitters = new CopyOnWriteArrayList<>();
    private final ObjectMapper objectMapper = new ObjectMapper();
    private final Map<String, List<IotCarPersonEvent>> eventMap;

    private final IotXfjyryRfidBindMapper xfjyryRfidBindMapper;
    private final IotXfclDeviceBindMapper xfclDeviceMapper;

    public ReceiverMessageHandler(IotXfjyryRfidBindMapper xfjyryRfidBindMapper,
                                  IotXfclDeviceBindMapper xfclDeviceMapper) {
        this.xfjyryRfidBindMapper = xfjyryRfidBindMapper;
        this.xfclDeviceMapper = xfclDeviceMapper;
        this.eventMap = new HashMap<>();
    }

    public void addEmitter(SseEmitter emitter) {
        emitters.add(emitter);
        emitter.onCompletion(() -> emitters.remove(emitter));
        emitter.onTimeout(() -> emitters.remove(emitter));
    }

    @Override
    public void handleMessage(Message<?> message) throws MessagingException {
        Object payload = message.getPayload();
        try {
            DeviceReport data = objectMapper.readValue(payload.toString(), DeviceReport.class);
            if ("device_report_probe_data".equals(data.getMethod())) {
                List<RfidTag> tagList = data.getData().getTagList();
                List<String> epcs = tagList.stream().map(RfidTag::getEpc).collect(Collectors.toList());
                String serialNo = data.getSn(); // 获取设备编号
                List<IotCarPersonEvent> eventList = new ArrayList<>();
                if (epcs != null && !epcs.isEmpty()) {
                    List<IotXfjyryRfidBindVo> userBindings = xfjyryRfidBindMapper.selectByEpcs(epcs);
                    // 在创建eventList之前，先将userBindings转换为Map
                    Map<String, IotXfjyryRfidBindVo> userBindingMap = userBindings.stream()
                        .collect(Collectors.toMap(IotXfjyryRfidBindVo::getEpc, binding -> binding));
                    eventList = tagList.stream().map(tag -> {
                        IotCarPersonEvent event = new IotCarPersonEvent();
                        event.setSerialNo(serialNo);
                        event.setEpc(tag.getEpc());
                        event.setAnt(tag.getAnt());
                        event.setRssi(tag.getRssi());
                        event.setFirstTime(new Date(tag.getFirstTime()));
                        event.setLastTime(new Date(tag.getLastTime()));
                        // 设置人员信息
                        IotXfjyryRfidBindVo vo = userBindingMap.get(tag.getEpc());
                        if (vo != null) {
                            event.setXm(vo.getXm());
                            event.setXfjyryId(vo.getXfjyryId());
                        }
                        return event;
                    }).collect(Collectors.toList());
                }
                IotXfclDeviceBindVo xfclInfo = xfclDeviceMapper.selectBySeriralNo(serialNo);
                eventMap.put(xfclInfo.getVehicleInfo().getJdchphm(), eventList);
                // 发送给所有连接的客户端
                emitters.forEach(emitter -> {
                    try {
                        emitter.send(SseEmitter.event()
                            .data(R.ok(eventMap)));
                    } catch (IOException e) {
                        emitter.completeWithError(e);
                        emitters.remove(emitter);
                    }
                });
            }
        } catch (Exception e) {
            System.err.println("Error processing message: " + e.getMessage());
        }
    }
}

